#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
	ui->message->installEventFilter(this);
	setObjectName("S0taChat");
	sota::connect((":8765/" + objectName()).toAscii(), SIGNAL(message(QString, QString, QString)), this, SLOT(on_message(QString, QString, QString)));
	sota::connect((":8766/" + objectName()).toAscii(), SIGNAL(file(QString,int,QByteArray,QString,QString,QByteArray)), this, SLOT(on_file(QString,int,QByteArray,QString,QString,QByteArray)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_send_clicked()
{
	reconnect();
	if (ui->message->toPlainText().length() > 0)
	{
		printToLog(true, ui->message->toPlainText());
		emit message(ui->message->toPlainText(), currentTime(), currentIp());
		ui->message->clear();
	}
}

void MainWindow::reconnect()
{
	if (cur_address != ui->address->currentText())
	{
		sota::disconnect(this, SIGNAL(message(QString, QString, QString)), 0, 0);
		sota::disconnect(this, SIGNAL(file(QString,int,QByteArray,QString,QString,QByteArray)), 0, 0);
		sota::connect(
				this,
				SIGNAL(message(QString, QString, QString)),
				(ui->address->currentText() + ":8765/" + objectName()).toAscii(),
				SLOT(on_message(QString, QString, QString)),
				sota::Xml
				); //here we use xml stream which is slower than binary data steam but portable
		sota::connect(
				this,
				SIGNAL(file(QString,int,QByteArray,QString,QString,QByteArray)),
				(ui->address->currentText() + ":8766/" + objectName()).toAscii(),
				SLOT(on_file(QString,int,QByteArray,QString,QString,QByteArray)),
				sota::DataStream
				); // here we use binary data stream which is faster than xml stream but not portable (Qt 4.2+ only)
		if (ui->address->findText(cur_address = ui->address->currentText()) == -1)
		{
			ui->address->addItem(cur_address);
		}
	}
}

void MainWindow::printToLog(bool _local, const QString & _text, const QString & _time, const QString & _ip)
{
	QCoreApplication::instance()->processEvents();
	if (_local)
	{
		ui->log->append("<font color=blue>" + _time + " " + _ip + " :</font> " + _text);
	}
	else
	{
		ui->log->append("<font color=red><i>" + _time + " " + _ip + " : </i></font>" + _text);
	}
}

void MainWindow::changeIp(const QString &_ip)
{
	ui->address->setEditText(_ip);
	reconnect();
}

void MainWindow::on_message(QString _text, QString _time, QString _ip)
{
	printToLog(false, _text, _time, _ip);
	changeIp(_ip);
}

void MainWindow::on_actionExit_triggered()
{
	QCoreApplication::instance()->quit();
}

bool MainWindow::eventFilter(QObject * _object, QEvent * _event)
{
	switch ((int)_event->type())
	{
	case QEvent::DragEnter:
		if (_object == ui->message) // check drag in message field
		{
			if (((QDragEnterEvent *)_event)->mimeData()->hasUrls())
			{
				((QDragEnterEvent *)_event)->acceptProposedAction(); // accepting files
				return true;
			}
		}
		break;
	case QEvent::Drop:
		if (_object == ui->message) // check drop in message field
		{
			reconnect();
			parseFiles(((QDropEvent *)_event)->mimeData()->urls()); // parse dropped files list
			return true;
		}
		break;
	}
	return QMainWindow::eventFilter(_object, _event);
}

void MainWindow::parseFiles(const QList<QUrl> & _urls)
{
	printToLog(true, "preparing to file transfer...");
	foreach (const QUrl & _url, _urls)
	{
		QFile _file((_url.path().indexOf('/') == 0) ? _url.path().remove(0, 1) : _url.path());
		if (_file.exists())
		{
			_file.open(QFile::ReadOnly);
			const QByteArray & _data = _file.readAll();
			_file.close();
			emit file(QFileInfo(_file.fileName()).fileName(), _file.size(), QCryptographicHash::hash(_data, QCryptographicHash::Md5), currentTime(), currentIp(), _data);
			printToLog(true, "transferring file \"" + QFileInfo(_file.fileName()).fileName() + "\" (size " + sizeMb(_file.size()) + " Mb)");
		}
	}
}

void MainWindow::on_file(QString _name, int _size, QByteArray _md5, QString _time, QString _ip, QByteArray _data)
{
	printToLog(false, "transferring file \"" + _name + "\" (size " + sizeMb(_size) + " Mb)", _time, _ip);
	changeIp(_ip);
	if (_md5 != QCryptographicHash::hash(_data, QCryptographicHash::Md5))
	{
		printToLog(false, "md5 checking failed");
		return;
	}
	if (_data.size() != _size)
	{
		printToLog(false, "size checking failed");
		return;
	}
	QString _path = QCoreApplication::instance()->applicationDirPath() + "/incoming/";
	QDir().mkpath(_path);
	QFile _file(_path + _name);
	_file.open(QFile::WriteOnly);
	_file.write(_data);
	_file.close();
	printToLog(true, "file \"" + _name + "\" received and saved to \"<a href=\"" + _path + "\">" + _path + "</a>\" folder");
}

